package com.allesblinkt.mucom.server;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;

import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.jmdns.JmDNS;
import javax.jmdns.ServiceInfo;

import mathematik.Vector2f;

import org.simpleframework.http.connect.SocketConnection;
import org.simpleframework.http.resource.Context;

import com.allesblinkt.mucom.client.NetController;
import com.allesblinkt.mucom.common.ClientItem;
import com.allesblinkt.mucom.common.Constants;
import com.allesblinkt.mucom.common.StatusRepresentation;

import processing.core.PApplet;
import processing.core.PFont;

@SuppressWarnings("serial")
public class ServerApp extends PApplet implements Constants {

	PFont fontBig;

	Logger logger;

	JmDNS jmdns;

	ServerController serverController;

	private float progress = 0;

	private SocketConnection connection;

	private StatusRepresentation statusRepresentation;

	public void setup() {
		logger = Logger.getLogger("ServerLogger");
		logger.setLevel(Level.ALL);

		size(640, 480);
		frameRate(30);

		initServer(SERVER_PORT);

		fontBig = loadFont("Helvetica-Bold-20.vlw");

		try {
			jmdns = JmDNS.create();

			jmdns.registerService(ServiceInfo.create(SERVICE_NAME, "sven",
					SERVER_PORT, "Gude Laune"));

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		System.out.println("inited jmdns");

		smooth();

		statusRepresentation = new StatusRepresentation(this);
	}

	public void draw() {
		background(255);

		fill(0);

		textFont(fontBig);
		text("Microcommunity Server     ", 20, 30);
		strokeWeight(1);
		stroke(0);
		line(20, 39, width - 20, 39);

		pushMatrix();
		rectMode(CENTER);
		noStroke();

		translate(370, 25);
		fill(0);

		float ellipseSize = (sin(progress) + 1) * 5 + 2;
		ellipse(0, 0, ellipseSize, ellipseSize);
		popMatrix();

		pushMatrix();
		rectMode(CORNER);

		noStroke();

		fill(0);

		Vector<ClientItem> purgeClients = new Vector<ClientItem>();

		float rotationStep = TWO_PI
				/ max(1, serverController.clientOrder().size());
		int count = 0;
		for (ClientItem client : serverController.clientOrder()) {
			long elapsed = System.currentTimeMillis() - client.getLastSeen();

			pushMatrix();
			translate(width / 2, height / 2);
			rotate(rotationStep * count);
			translate(30, 0);

			rectMode(CENTER);
			float alpha = (sin(progress) + 1) * 50 + 155;

			if (client.equals(serverController.getActiveClient())) {
				fill(200, 0, 0, alpha);
			} else {
				fill(0, alpha);
			}

			ellipse(0, 0, 30, 30);

			if (elapsed < 200) {
				fill(255);
				ellipse(0, 0, 10, 10);

			}

			fill(0);

			textFont(fontBig);
			text(client.getHostname(), 30, 0);
			textFont(fontBig, 10);

			text(client.getOs(), 30, 15, 10);

			popMatrix();

			if (elapsed > CLIENT_IDLE_TIMEOUT * 1000) {
				purgeClients.add(client); // Mark for purging
			}

			count++;

		}

		/* Purge inactive clients */// TODO: move to ServerController
		for (ClientItem client : purgeClients) {
			serverController.clientOrder().remove(client);
			serverController.clients().remove(client.getHash());

			if (client.equals(serverController.getActiveClient())) {
				serverController.setActiveClient(null);
			}

			if (client.equals(serverController.getLastActiveClient())) {
				serverController.setLastActiveClient(null);
			}
		}

		popMatrix();
		
		statusRepresentation.mouseAt(mouseX ,  mouseY);
		statusRepresentation.moveTo(new Vector2f(width/2, height/2));
		statusRepresentation.draw();
		

		progress += 0.05f;

		
	}

	public void stop() {

		System.out.println("I am in stop ");

		try {
			jmdns.close();
		} catch (Exception e) {
			System.out.println(e);
		}

		System.out.println("unregistered services");
		try {
			connection.close();

		} catch (Exception e) {
			System.out.println(e);
		}
		System.out.println("stopped server");

		super.stop();

	}

	public static void main(String args[]) {
		PApplet.main(new String[] { ServerApp.class.getCanonicalName() });
	}

	private void initServer(int thePort) {

		try {
			serverController = new ServerController();
			

			
			connection = new SocketConnection(serverController);
			

			SocketAddress address = new InetSocketAddress(thePort);

			connection.connect(address);

			logger.log(Level.INFO, "Server started successfully on port "
					+ thePort);

		} catch (Exception e) {
			logger.log(Level.SEVERE, "Server failed to start \n Reason:"
					+ e.getLocalizedMessage());

			die("Server failed to Start", e);
		}

	}

}
